home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fsio / fsioDevice.c < prev    next >
C/C++ Source or Header  |  1991-03-30  |  43KB  |  1,370 lines

  1. /* 
  2.  * fsDevice.c --
  3.  *
  4.  *    Routines to manage devices.  
  5.  *    The handle for a device is uniquified using the device type and
  6.  *    unit number.  This ensures that different filesystem names for
  7.  *    the same device map to the same device I/O handle.
  8.  *
  9.  *    There are two sets of routines here.  There are routines internal
  10.  *    to the filesystem that are used to open, close, read, write, etc.
  11.  *    a device stream.  Then there are some external routines exported
  12.  *    for use by device drivers.  Fs_NotifyReader and Fs_NotifyWriter
  13.  *    are used by interrupt handlers to indicate a device is ready.
  14.  *    Then there are a handful of conversion routines for mapping
  15.  *    from file system block numbers to disk addresses.
  16.  *
  17.  * Copyright 1987 Regents of the University of California
  18.  * All rights reserved.
  19.  * Permission to use, copy, modify, and distribute this
  20.  * software and its documentation for any purpose and without
  21.  * fee is hereby granted, provided that the above copyright
  22.  * notice appear in all copies.  The University of California
  23.  * makes no representations about the suitability of this
  24.  * software for any purpose.  It is provided "as is" without
  25.  * express or implied warranty.
  26.  */
  27.  
  28. #ifndef lint
  29. static char rcsid[] = "$Header: /sprite/src/kernel/fsio/RCS/fsioDevice.c,v 9.9 91/03/30 17:12:03 mgbaker Exp $ SPRITE (Berkeley)";
  30. #endif not lint
  31.  
  32.  
  33. #include <sprite.h>
  34.  
  35. #include <fs.h>
  36. #include <fsutil.h>
  37. #include <fsconsist.h>
  38. #include <fsio.h>
  39. #include <fsNameOps.h>
  40. #include <fsdm.h>
  41. #include <fsioLock.h>
  42. #include <fsprefix.h>
  43. #include <fsrmt.h>
  44. #include <dev.h>
  45. #include <rpc.h>
  46. #include <fsStat.h>
  47. #include <fsioDevice.h>
  48. #include <devFsOpTable.h>
  49. #include <devTypes.h>
  50.  
  51. #include <stdio.h>
  52.  
  53. /*
  54.  * INET is defined so a file server can be used to open the
  55.  * special device file corresponding to a kernel-based ipServer
  56.  */
  57. #undef INET
  58. #ifdef INET
  59. #include <netInet.h>
  60. /*
  61.  * DEV_PLACEHOLDER_2    is defined in devTypesInt.h, which is not exported.
  62.  *    This is an ugly hack, anyway, so we just define it here.  3/89
  63.  *    The best solution is to define a new disk file type and not
  64.  *    use Fsio_DeviceNameOpen at all.
  65.  */
  66. #define DEV_PLACEHOLDER_2    3
  67. static int sockCounter = 0;
  68. #endif
  69.  
  70. static void ReadNotify _ARGS_((ClientData data, Proc_CallInfo *callInfoPtr));
  71. static void WriteNotify _ARGS_((ClientData data, Proc_CallInfo *callInfoPtr));
  72. static void ExceptionNotify _ARGS_((ClientData data, 
  73.                 Proc_CallInfo *callInfoPtr));
  74.  
  75. extern ReturnStatus FsioDeviceCloseInt _ARGS_((
  76.         Fsio_DeviceIOHandle *devHandlePtr, int useFlags, int refs, 
  77.         int writes));
  78.  
  79.  
  80.  
  81. /*
  82.  *----------------------------------------------------------------------
  83.  *
  84.  * FsioDeviceHandleInit --
  85.  *
  86.  *    Initialize a handle for a local device.
  87.  *
  88.  * Results:
  89.  *    TRUE if the handle was already found, FALSE if not.
  90.  *
  91.  * Side effects:
  92.  *    Create and install a handle for the device.  It is returned locked
  93.  *    and with its reference count incremented if SUCCESS is returned.
  94.  *
  95.  *----------------------------------------------------------------------
  96.  */
  97. Boolean
  98. FsioDeviceHandleInit(fileIDPtr, name, newHandlePtrPtr)
  99.     Fs_FileID        *fileIDPtr;
  100.     char        *name;
  101.     Fsio_DeviceIOHandle    **newHandlePtrPtr;
  102. {
  103.     register Boolean found;
  104.     register Fsio_DeviceIOHandle *devHandlePtr;
  105.  
  106.     found = Fsutil_HandleInstall(fileIDPtr, sizeof(Fsio_DeviceIOHandle), name,
  107.             FALSE, (Fs_HandleHeader **)newHandlePtrPtr);
  108.     if (!found) {
  109.     devHandlePtr = *newHandlePtrPtr;
  110.     List_Init(&devHandlePtr->clientList);
  111.     devHandlePtr->use.ref = 0;
  112.     devHandlePtr->use.write = 0;
  113.     devHandlePtr->use.exec = 0;
  114.     devHandlePtr->device.serverID = fileIDPtr->serverID;
  115.     devHandlePtr->device.type = fileIDPtr->major;
  116.     devHandlePtr->device.unit = fileIDPtr->minor;
  117.     devHandlePtr->device.data = (ClientData)NIL;
  118.     devHandlePtr->flags = 0;
  119.     Fsio_LockInit(&devHandlePtr->lock);
  120.     devHandlePtr->modifyTime = 0;
  121.     devHandlePtr->accessTime = 0;
  122.     List_Init(&devHandlePtr->readWaitList);
  123.     List_Init(&devHandlePtr->writeWaitList);
  124.     List_Init(&devHandlePtr->exceptWaitList);
  125.     devHandlePtr->notifyFlags = 0;
  126.     fs_Stats.object.devices++;
  127.     }
  128.     return(found);
  129. }
  130.  
  131.  
  132. /*
  133.  *----------------------------------------------------------------------
  134.  *
  135.  * Fsio_DeviceNameOpen --
  136.  *
  137.  *    This routine sets up an ioFileID for the device based on the
  138.  *    device file found on the name server.  This is called on the name
  139.  *    server in two cases, when a client is doing an open, and when
  140.  *    it is doing a Get/Set attributes on a device file name.   At
  141.  *    open time some additional attributes are returned to the client
  142.  *    for caching at the I/O server, and a streamID is chosen.
  143.  *    Note that no state is kept about the device client here on the
  144.  *    name server.  The device client open routine sets up that state.
  145.  *
  146.  * Results:
  147.  *    SUCCESS, *ioFileIDPtr has the I/O file ID, and *clientDataPtr
  148.  *    references the device state.
  149.  *
  150.  * Side effects:
  151.  *    Choose the fileID for the clients stream.
  152.  *    Allocates memory to hold the stream data.
  153.  *
  154.  *----------------------------------------------------------------------
  155.  */
  156. /*ARGSUSED*/
  157. ReturnStatus
  158. Fsio_DeviceNameOpen(handlePtr, openArgsPtr, openResultsPtr)
  159.     Fsio_FileIOHandle    *handlePtr;    /* A handle obtained by FslclLookup.
  160.                      * Should be locked upon entry,
  161.                      * is unlocked upon exit. */
  162.      Fs_OpenArgs        *openArgsPtr;    /* Standard open arguments */
  163.      Fs_OpenResults    *openResultsPtr;/* For returning ioFileID, streamID,
  164.                      * and Fsio_DeviceState */
  165. {
  166.     register Fsdm_FileDescriptor *descPtr = handlePtr->descPtr;
  167.     register Fsio_DeviceState *deviceDataPtr;
  168.     register Fs_FileID *ioFileIDPtr = &openResultsPtr->ioFileID;
  169.  
  170.     ioFileIDPtr->serverID = descPtr->devServerID;
  171.     if (ioFileIDPtr->serverID == FS_LOCALHOST_ID) {
  172.     /*
  173.      * Map this "common" or "generic" device to the instance of
  174.      * the device on the process's logical home node.
  175.      */
  176.     ioFileIDPtr->serverID = openArgsPtr->migClientID;
  177.     }
  178.     ioFileIDPtr->major = descPtr->devType;
  179.     ioFileIDPtr->minor = descPtr->devUnit;
  180. #ifdef INET
  181.     /*
  182.      * Hack in support for sockets by mapping a special device type
  183.      * to sockets.  This needs to be replaced with a new type of disk file.
  184.      */
  185.     if (descPtr->devType == DEV_PLACEHOLDER_2) {
  186.     ioFileIDPtr->major = rpc_SpriteID;
  187.     ioFileIDPtr->minor = sockCounter++;
  188.     switch(descPtr->devUnit) {
  189.         case NET_IP_PROTOCOL_IP:
  190.         ioFileIDPtr->type = FSIO_RAW_IP_STREAM;
  191.         break;
  192.         case NET_IP_PROTOCOL_UDP:
  193.         ioFileIDPtr->type = FSIO_UDP_STREAM;
  194.         break;
  195.         case NET_IP_PROTOCOL_TCP:
  196.         ioFileIDPtr->type = FSIO_TCP_STREAM;
  197.         break;
  198.         default:
  199.         ioFileIDPtr->major = descPtr->devType;
  200.         ioFileIDPtr->minor = descPtr->devUnit;
  201.         if (ioFileIDPtr->serverID == openArgsPtr->clientID) {
  202.             ioFileIDPtr->type = FSIO_LCL_DEVICE_STREAM;
  203.         } else {
  204.             ioFileIDPtr->type = FSIO_RMT_DEVICE_STREAM;
  205.         }
  206.         break;
  207.     }
  208.     } else
  209. #endif
  210.     if (ioFileIDPtr->serverID == openArgsPtr->clientID) {
  211.     ioFileIDPtr->type = FSIO_LCL_DEVICE_STREAM;
  212.     } else {
  213.     ioFileIDPtr->type = FSIO_RMT_DEVICE_STREAM;
  214.     }
  215.     if (openArgsPtr->useFlags != 0) {
  216.     /*
  217.      * Truely preparing for an open.
  218.      * Return the current modify/access times for the I/O server's cache.
  219.      */
  220.     deviceDataPtr = mnew(Fsio_DeviceState);
  221.     deviceDataPtr->modifyTime = descPtr->dataModifyTime;
  222.     deviceDataPtr->accessTime = descPtr->accessTime;
  223.     /*
  224.      * Choose a streamID for the client that points to the device server.
  225.      */
  226.     Fsio_StreamCreateID(ioFileIDPtr->serverID, &openResultsPtr->streamID);
  227.     deviceDataPtr->streamID = openResultsPtr->streamID;
  228.  
  229.     openResultsPtr->streamData = (ClientData)deviceDataPtr;
  230.     openResultsPtr->dataSize = sizeof(Fsio_DeviceState);
  231.     }
  232.     Fsutil_HandleUnlock(handlePtr);
  233.     return(SUCCESS);
  234. }
  235.  
  236. /*
  237.  *----------------------------------------------------------------------
  238.  *
  239.  * Fsio_DeviceIoOpen --
  240.  *
  241.  *    Complete opening of a local device.  This is called on the I/O
  242.  *    server and sets up state concerning this client.  The device
  243.  *    driver open routine is called to set up the device.  If that
  244.  *    succeeds then the device's Handle is installed and set up.
  245.  *    This includes incrementing client's use counts and the
  246.  *    global use counts in the handle.
  247.  *
  248.  * Results:
  249.  *    SUCCESS or a device dependent open error code.
  250.  *
  251.  * Side effects:
  252.  *    Sets up and installs the device's ioHandle.  The device-type open
  253.  *    routine is called on the I/O server.  The handle is unlocked
  254.  *    upon exit, but its reference count has been incremented.
  255.  *
  256.  *----------------------------------------------------------------------
  257.  */
  258. ReturnStatus
  259. Fsio_DeviceIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name, ioHandlePtrPtr)
  260.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  261.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  262.     int            clientID;    /* Host doing the open */
  263.     ClientData        streamData;    /* Reference to Fsio_DeviceState struct */
  264.     char        *name;        /* File name for error msgs */
  265.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a locked handle set up for
  266.                      * I/O to a device, NIL if failure. */
  267. {
  268.     ReturnStatus         status;
  269.     Boolean            found;
  270.     register Fsio_DeviceState    *deviceDataPtr;
  271.     register Fsio_DeviceIOHandle    *devHandlePtr;
  272.     Fsio_DeviceIOHandle        *tDevHandlePtr;    /* tempory devHandlePtr */
  273.     register Fs_Stream        *streamPtr;
  274.     register int        flags = *flagsPtr;
  275.  
  276.     deviceDataPtr = (Fsio_DeviceState *)streamData;
  277.     *ioHandlePtrPtr = (Fs_HandleHeader *)NIL;
  278.  
  279.     found = FsioDeviceHandleInit(ioFileIDPtr, name, &tDevHandlePtr);
  280.     devHandlePtr = tDevHandlePtr;
  281.     /*
  282.      * The device driver open routine gets the device specification,
  283.      * the useFlags, and a token passed to Fs_NotifyReader
  284.      * or Fs_NotifyWriter when the device becomes ready for I/O.
  285.      */
  286.     if (DEV_TYPE_INDEX(devHandlePtr->device.type) >= devNumDevices) {
  287.     status = FS_DEVICE_OP_INVALID;
  288.     } else {
  289.     status = (*devFsOpTable[DEV_TYPE_INDEX(devHandlePtr->device.type)].open)
  290.             (&devHandlePtr->device, flags, 
  291.              (Fs_NotifyToken)devHandlePtr, &devHandlePtr->flags);
  292.     }
  293.     if (status == SUCCESS) {
  294.     if (!found) {
  295.         /*
  296.          * Absorb the I/O attributes returned from the SrvOpen routine
  297.          * on the file server.
  298.          */
  299.         devHandlePtr->modifyTime = deviceDataPtr->modifyTime;
  300.         devHandlePtr->accessTime = deviceDataPtr->accessTime;
  301.     }
  302.     /*
  303.      * Trace the client, and then update our overall use counts.
  304.      * The client is recorded at the stream level to support migration,
  305.      * and at the I/O handle level for regular I/O.
  306.      */
  307.     (void)Fsconsist_IOClientOpen(&devHandlePtr->clientList, clientID, flags, FALSE);
  308.  
  309.     streamPtr = Fsio_StreamAddClient(&deviceDataPtr->streamID, clientID,
  310.             (Fs_HandleHeader *)devHandlePtr, flags,
  311.             name, (Boolean *)NIL, (Boolean *)NIL);
  312.     Fsutil_HandleRelease(streamPtr, TRUE);
  313.  
  314.     devHandlePtr->use.ref++;
  315.     if (flags & FS_WRITE) {
  316.         devHandlePtr->use.write++;
  317.     }
  318.     *ioHandlePtrPtr = (Fs_HandleHeader *)devHandlePtr;
  319.     Fsutil_HandleUnlock(devHandlePtr);
  320.     } else {
  321.     Fsutil_HandleRelease(devHandlePtr, TRUE);
  322.     }
  323.     free((Address) deviceDataPtr);
  324.     return(status);
  325. }
  326.  
  327. /*
  328.  *----------------------------------------------------------------------
  329.  *
  330.  * Fsio_DeviceClose --
  331.  *
  332.  *    Close a stream to a device.  We just need to clean up our state with
  333.  *    the device driver.  The file server that named the device file keeps
  334.  *    no state about us, so we don't have to contact it.
  335.  *
  336.  * FIX ME: need to write back access/modify times to name server
  337.  *    Can use fs_AttrOpTable and the nameInfoPtr->fileID as long
  338.  *    if the shadow stream on the I/O server is set up enough.
  339.  *
  340.  * Results:
  341.  *    SUCCESS.
  342.  *
  343.  * Side effects:
  344.  *    Calls the device type close routine.
  345.  *
  346.  *----------------------------------------------------------------------
  347.  */
  348. /*ARGSUSED*/
  349. #ifndef SOSP91
  350. ReturnStatus
  351. Fsio_DeviceClose(streamPtr, clientID, procID, flags, size, data)
  352. #else
  353. ReturnStatus
  354. Fsio_DeviceClose(streamPtr, clientID, procID, flags, size, data, offsetPtr,
  355.     rwFlagsPtr)
  356. #endif
  357.     Fs_Stream        *streamPtr;    /* Stream to device */
  358.     int            clientID;    /* HostID of client closing */
  359.     Proc_PID        procID;        /* ID of closing process */
  360.     int            flags;        /* Flags from the stream being closed */
  361.     int            size;        /* Should be zero */
  362.     ClientData        data;        /* IGNORED */
  363. #ifdef SOSP91
  364.     int            *offsetPtr;    /* Not used. */
  365.     int            *rwFlagsPtr;    /* Not used. */
  366. #endif
  367. {
  368.     ReturnStatus        status;
  369.     register Fsio_DeviceIOHandle    *devHandlePtr =
  370.         (Fsio_DeviceIOHandle *)streamPtr->ioHandlePtr;
  371.     Boolean            cache = FALSE;
  372.  
  373.     if (!Fsconsist_IOClientClose(&devHandlePtr->clientList, clientID, flags, &cache)) {
  374.     printf("Fsio_DeviceClose, client %d unknown for device <%d,%d>\n",
  375.           clientID, devHandlePtr->hdr.fileID.major,
  376.           devHandlePtr->hdr.fileID.minor);
  377.     Fsutil_HandleRelease(devHandlePtr, TRUE);
  378.     return(FS_STALE_HANDLE);
  379.     }
  380.     /*
  381.      * Clean up locks, then
  382.      * clean up summary use counts and call driver's close routine.
  383.      */
  384.     Fsio_LockClose(&devHandlePtr->lock, &streamPtr->hdr.fileID);
  385.  
  386.     status = FsioDeviceCloseInt(devHandlePtr, flags, 1, (flags & FS_WRITE) != 0);
  387.     /*
  388.      * We don't bother to remove the handle here if the device isn't
  389.      * being used.  Instead we let the handle get scavenged.
  390.      */
  391.     Fsutil_HandleRelease(devHandlePtr, TRUE);
  392.  
  393.     return(status);
  394. }
  395.  
  396. /*
  397.  * ----------------------------------------------------------------------------
  398.  *
  399.  * Fsio_DeviceClientKill --
  400.  *
  401.  *    Called when a client is assumed down.  This cleans up the
  402.  *    references due to the client.
  403.  *    
  404.  *
  405.  * Results:
  406.  *    SUCCESS.
  407.  *
  408.  * Side effects:
  409.  *    Removes the client list entry for the client and adjusts the
  410.  *    use counts on the file.  This unlocks the handle.
  411.  *
  412.  * ----------------------------------------------------------------------------
  413.  *
  414.  */
  415. ReturnStatus
  416. FsioDeviceCloseInt(devHandlePtr, useFlags, refs, writes)
  417.     Fsio_DeviceIOHandle *devHandlePtr;    /* Device handle */
  418.     int useFlags;            /* Flags from the stream */
  419.     int refs;                /* Number of refs to close */
  420.     int writes;                /* Number of these that were writing */
  421. {
  422.     if (refs > 0) {
  423.     devHandlePtr->use.ref -= refs;
  424.     }
  425.     if (writes > 0) {
  426.     devHandlePtr->use.write -= writes;
  427.     }
  428.  
  429.     if (devHandlePtr->use.ref < 0 || devHandlePtr->use.write < 0) {
  430.     panic("FsioDeviceCloseInt <%d,%d> ref %d, write %d\n",
  431.         devHandlePtr->hdr.fileID.major, devHandlePtr->hdr.fileID.minor,
  432.         devHandlePtr->use.ref, devHandlePtr->use.write);
  433.     }
  434.  
  435.     return (*devFsOpTable[DEV_TYPE_INDEX(devHandlePtr->device.type)].close)
  436.         (&devHandlePtr->device, useFlags, devHandlePtr->use.ref,
  437.         devHandlePtr->use.write);
  438. }
  439.  
  440. /*
  441.  * ----------------------------------------------------------------------------
  442.  *
  443.  * Fsio_DeviceClientKill --
  444.  *
  445.  *    Called when a client is assumed down.  This cleans up the
  446.  *    references due to the client.
  447.  *    
  448.  *
  449.  * Results:
  450.  *    SUCCESS.
  451.  *
  452.  * Side effects:
  453.  *    Removes the client list entry for the client and adjusts the
  454.  *    use counts on the file.  This unlocks the handle.
  455.  *
  456.  * ----------------------------------------------------------------------------
  457.  *
  458.  */
  459. /*ARGSUSED*/
  460. void
  461. Fsio_DeviceClientKill(hdrPtr, clientID)
  462.     Fs_HandleHeader    *hdrPtr;    /* File to clean up */
  463.     int            clientID;    /* Host assumed down */
  464. {
  465.     register Fsio_DeviceIOHandle *devHandlePtr = (Fsio_DeviceIOHandle *)hdrPtr;
  466.     int refs, writes, execs;
  467.  
  468.     /*
  469.      * Remove the client from the list of users, and see what it was doing.
  470.      */
  471.     Fsconsist_IOClientKill(&devHandlePtr->clientList, clientID, &refs, &writes, &execs);
  472.  
  473.     Fsio_LockClientKill(&devHandlePtr->lock, clientID);
  474.  
  475.     if (refs > 0) {
  476.     int useFlags = FS_READ;        /* Have to assume this,
  477.                      * which might be wrong for syslog */
  478.     if (writes > 0) {
  479.         useFlags |= FS_WRITE;
  480.     }
  481.     (void)FsioDeviceCloseInt(devHandlePtr, useFlags, refs, writes);
  482.     }
  483.     Fsutil_HandleUnlock(devHandlePtr);
  484. }
  485.  
  486. /*
  487.  * ----------------------------------------------------------------------------
  488.  *
  489.  * Fsio_DeviceScavenge --
  490.  *
  491.  *    Called periodically to see if this handle is still needed.
  492.  *    
  493.  *
  494.  * Results:
  495.  *    TRUE if the handle was removed.
  496.  *
  497.  * Side effects:
  498.  *    Removes the handle if it isn't referenced anymore and there
  499.  *    are no remote clients.
  500.  *
  501.  * ----------------------------------------------------------------------------
  502.  *
  503.  */
  504. Boolean
  505. Fsio_DeviceScavenge(hdrPtr)
  506.     Fs_HandleHeader    *hdrPtr;    /* File to clean up */
  507. {
  508.     register Fsio_DeviceIOHandle *handlePtr = (Fsio_DeviceIOHandle *)hdrPtr;
  509.  
  510.     if (handlePtr->use.ref == 0) {
  511.     /*
  512.      * Remove handles for devices with no users.
  513.      */
  514.     Fsutil_WaitListDelete(&handlePtr->readWaitList);
  515.     Fsutil_WaitListDelete(&handlePtr->writeWaitList);
  516.     Fsutil_WaitListDelete(&handlePtr->exceptWaitList);
  517.     Fsutil_HandleRemove(handlePtr);
  518.     fs_Stats.object.devices--;
  519.     return(TRUE);
  520.     } else {
  521.         Fsutil_HandleUnlock(handlePtr);
  522.     return(FALSE);
  523.     }
  524. }
  525.  
  526. /*
  527.  *----------------------------------------------------------------------
  528.  *
  529.  * Fsio_VanillaDevReopen --
  530.  *
  531.  *    This is a simplified device driver re-open procedure.  It is called
  532.  *    from Fsrmt_DeviceReopen via the device operation switch.  It, in turn,
  533.  *    calls back through the device switch to the regular device open
  534.  *    procedure.  Form many simple devices this is sufficient for a reopen.
  535.  *
  536.  * Results:
  537.  *    None.
  538.  *
  539.  * Side effects:
  540.  *    None.
  541.  *    
  542.  *
  543.  *----------------------------------------------------------------------
  544.  */
  545. /*ARGSUSED*/
  546. ReturnStatus
  547. Fsio_VanillaDevReopen(devicePtr, refs, writes, notifyToken)
  548.     Fs_Device *devicePtr;    /* Identifies the device */
  549.     int refs;            /* Number of streams to the device */
  550.     int writes;            /* Number of those that are for writing */
  551.     Fs_NotifyToken notifyToken;    /* Used with Fsio_DevNotifyReader */
  552. {
  553.     int devIndex = DEV_TYPE_INDEX(devicePtr->type);
  554.     int useFlags = 0;
  555.     int flags;
  556.  
  557.     if (refs > 0) {
  558.     useFlags |= FS_READ;
  559.     }
  560.     if (writes > 0) {
  561.     useFlags |= FS_WRITE;
  562.     }
  563.     return((*devFsOpTable[devIndex].open)
  564.                 (devicePtr, useFlags, notifyToken, &flags));
  565. }
  566.  
  567. /*
  568.  * ----------------------------------------------------------------------------
  569.  *
  570.  * Fsio_DeviceMigClose --
  571.  *
  572.  *    Release a reference from a Device I/O handle.
  573.  *    
  574.  * Results:
  575.  *    SUCCESS.
  576.  *
  577.  * Side effects:
  578.  *    Release the I/O handle.
  579.  *
  580.  * ----------------------------------------------------------------------------
  581.  *
  582.  */
  583. /*ARGSUSED*/
  584. ReturnStatus
  585. Fsio_DeviceMigClose(hdrPtr, flags)
  586.     Fs_HandleHeader *hdrPtr;    /* File being encapsulated */
  587.     int flags;            /* Use flags from the stream */
  588. {
  589.     panic( "Fsio_DeviceMigClose called\n");
  590.     Fsutil_HandleRelease(hdrPtr, FALSE);
  591.     return(SUCCESS);
  592. }
  593.  
  594.  
  595. /*
  596.  * ----------------------------------------------------------------------------
  597.  *
  598.  * Fsio_DeviceMigrate --
  599.  *
  600.  *    This takes care of transfering references from one client to the other.
  601.  *    A useful side-effect of this routine is    to properly set the type in
  602.  *    the ioFileID, either FSIO_LCL_DEVICE_STREAM or FSIO_RMT_DEVICE_STREAM.
  603.  *    In the latter case FsRmtDevoceMigrate is called to do all the work.
  604.  *
  605.  * Results:
  606.  *    An error status if the I/O handle can't be set-up.
  607.  *    Otherwise SUCCESS is returned, *flagsPtr may have the FS_RMT_SHARED
  608.  *    bit set, and *sizePtr and *dataPtr are set to reference Fsio_DeviceState.
  609.  *
  610.  * Side effects:
  611.  *    Sets the correct stream type on the ioFileID.
  612.  *    Shifts client references from the srcClient to the destClient.
  613.  *    Set up and return Fsio_DeviceState for use by the MigEnd routine.
  614.  *
  615.  * ----------------------------------------------------------------------------
  616.  *
  617.  */
  618. /*ARGSUSED*/
  619. ReturnStatus
  620. Fsio_DeviceMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr, sizePtr, dataPtr)
  621.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  622.     int        dstClientID;    /* ID of target client */
  623.     int        *flagsPtr;    /* In/Out Stream usage flags */
  624.     int        *offsetPtr;    /* Return - new stream offset */
  625.     int        *sizePtr;    /* Return - sizeof(Fsio_DeviceState) */
  626.     Address    *dataPtr;    /* Return - pointer to Fsio_DeviceState */
  627. {
  628.     Fsio_DeviceIOHandle            *devHandlePtr;
  629.     Boolean                closeSrcClient;
  630.  
  631.     if (migInfoPtr->ioFileID.serverID != rpc_SpriteID) {
  632.     /*
  633.      * The device was local, which is why we were called, but is now remote.
  634.      */
  635.     migInfoPtr->ioFileID.type = FSIO_RMT_DEVICE_STREAM;
  636.     return(FsrmtDeviceMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr,
  637.         sizePtr, dataPtr));
  638.     }
  639.     migInfoPtr->ioFileID.type = FSIO_LCL_DEVICE_STREAM;
  640.     if (!FsioDeviceHandleInit(&migInfoPtr->ioFileID, (char *)NIL, &devHandlePtr)){
  641.     printf(
  642.         "Fsio_DeviceMigrate, I/O handle <%d,%d> not found\n",
  643.          migInfoPtr->ioFileID.major, migInfoPtr->ioFileID.minor);
  644.     return(FS_FILE_NOT_FOUND);
  645.     }
  646.     /*
  647.      * At the stream level, add the new client to the set of clients
  648.      * for the stream, and check for any cross-network stream sharing.
  649.      */
  650.     Fsio_StreamMigClient(migInfoPtr, dstClientID, (Fs_HandleHeader *)devHandlePtr,
  651.             &closeSrcClient);
  652.     /*
  653.      * Adjust use counts on the I/O handle to reflect any new sharing.
  654.      */
  655.     Fsio_MigrateUseCounts(migInfoPtr->flags, closeSrcClient, &devHandlePtr->use);
  656.  
  657.     /*
  658.      * Move the client at the I/O handle level.
  659.      */
  660.     Fsio_MigrateClient(&devHandlePtr->clientList, migInfoPtr->srcClientID,
  661.             dstClientID, migInfoPtr->flags, closeSrcClient);
  662.  
  663.     *sizePtr = 0;
  664.     *dataPtr = (Address)NIL;
  665.     *flagsPtr = migInfoPtr->flags;
  666.     *offsetPtr = migInfoPtr->offset;
  667.     /*
  668.      * We don't need this reference on the I/O handle; there is no change.
  669.      */
  670.     Fsutil_HandleRelease(devHandlePtr, TRUE);
  671.     return(SUCCESS);
  672. }
  673.  
  674. /*
  675.  * ----------------------------------------------------------------------------
  676.  *
  677.  * Fsio_DeviceMigOpen --
  678.  *
  679.  *    Complete setup of a FS_DEVICE_STREAM after migration to the I/O server.
  680.  *    The migrate routine has done the work of shifting use counts
  681.  *    at the stream and I/O handle level.  This routine's job is
  682.  *    to increment the low level I/O handle reference count to reflect
  683.  *    the existence of a new stream to the I/O handle.
  684.  *
  685.  * Results:
  686.  *    None.
  687.  *
  688.  * Side effects:
  689.  *    None.
  690.  *
  691.  * ----------------------------------------------------------------------------
  692.  *
  693.  */
  694. /*ARGSUSED*/
  695. ReturnStatus
  696. Fsio_DeviceMigOpen(migInfoPtr, size, data, hdrPtrPtr)
  697.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  698.     int        size;        /* Zero */
  699.     ClientData    data;        /* NIL */
  700.     Fs_HandleHeader **hdrPtrPtr;    /* Return - handle for the file */
  701. {
  702.     register Fsio_DeviceIOHandle *devHandlePtr;
  703.  
  704.     devHandlePtr = Fsutil_HandleFetchType(Fsio_DeviceIOHandle, &migInfoPtr->ioFileID);
  705.     if (devHandlePtr == (Fsio_DeviceIOHandle *)NIL) {
  706.     panic( "Fsio_DeviceMigOpen, no handlel\n");
  707.     return(FAILURE);
  708.     } else {
  709.     Fsutil_HandleUnlock(devHandlePtr);
  710.     *hdrPtrPtr = (Fs_HandleHeader *)devHandlePtr;
  711.     return(SUCCESS);
  712.     }
  713. }
  714.  
  715. /*
  716.  *----------------------------------------------------------------------
  717.  *
  718.  * Fsio_DeviceRead --
  719.  *
  720.  *      Read on a stream connected to a local peripheral device.
  721.  *    This branches to the driver routine after setting up buffers.
  722.  *    This is called from Fs_Read and from Fsrmt_RpcRead.
  723.  *
  724.  * Results:
  725.  *    SUCCESS unless there was an address error or I/O error.
  726.  *
  727.  * Side effects:
  728.  *    Read the device.
  729.  *
  730.  *----------------------------------------------------------------------
  731.  */
  732. ReturnStatus
  733. Fsio_DeviceRead(streamPtr, readPtr, remoteWaitPtr, replyPtr)
  734.     Fs_Stream        *streamPtr;    /* Open stream to the device. */
  735.     Fs_IOParam        *readPtr;    /* Read parameter block. */
  736.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  737.     Fs_IOReply        *replyPtr;    /* Signal to return, if any,
  738.                      * plus the amount read. */
  739. {
  740.     register Fsio_DeviceIOHandle    *devHandlePtr =
  741.         (Fsio_DeviceIOHandle *)streamPtr->ioHandlePtr;
  742.     register ReturnStatus status;
  743.     register Fs_Device    *devicePtr;
  744.     int         flags;
  745.     Address userBuffer;
  746.     Boolean copy;
  747.  
  748.  
  749.     userBuffer = (Address) NIL;
  750.     flags = devHandlePtr->flags;
  751.     /*
  752.      * Don't lock if the device driver informed us upon open that 
  753.      * it doesn't want it.
  754.      */
  755.     if (!(flags & FS_DEV_DONT_LOCK)) { 
  756.     Fsutil_HandleLock(devHandlePtr);
  757.     }
  758.     /*
  759.      * Because the read could take a while and we aren't mapping in
  760.      * buffers, we have to allocate an extra buffer here so the
  761.      * buffer address is valid when the device's interrupt handler
  762.      * does its DMA. Don't do this malloc and copy if the device
  763.      * driver said it would handle it.
  764.      */
  765.     copy = (readPtr->flags & FS_USER) && !(flags & FS_DEV_DONT_COPY);
  766.     if (copy) {
  767.     userBuffer = readPtr->buffer;
  768.     readPtr->buffer = (Address)malloc(readPtr->length);
  769.     }
  770.  
  771.     /*
  772.      * Put the process onto the read-wait list before attempting the read.
  773.      * This is to prevent races with the device's notification which
  774.      * happens from an interrupt handler.
  775.      */
  776.     Fsutil_WaitListInsert(&devHandlePtr->readWaitList, remoteWaitPtr);
  777.     devicePtr = &devHandlePtr->device;
  778.     status = (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].read)(devicePtr,
  779.         readPtr, replyPtr);
  780.     if (copy) {
  781.         if (Vm_CopyOut(replyPtr->length, readPtr->buffer, userBuffer) != SUCCESS) {
  782.         if (status == SUCCESS) {
  783.         status = SYS_ARG_NOACCESS;
  784.         }
  785.     }
  786.     free(readPtr->buffer);
  787.     readPtr->buffer = userBuffer;
  788.     }
  789.     if (status != FS_WOULD_BLOCK) {
  790.     Fsutil_WaitListRemove(&devHandlePtr->readWaitList, remoteWaitPtr);
  791.     }
  792.     devHandlePtr->accessTime = Fsutil_TimeInSeconds();
  793.     fs_Stats.gen.deviceBytesRead += replyPtr->length;
  794. #ifdef SOSP91
  795.     if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  796.     if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  797.         (proc_RunningProcesses[0]->genFlags &
  798.         (PROC_FOREIGN | PROC_MIGRATING))) {
  799.         fs_SospMigStats.gen.deviceBytesRead += replyPtr->length; 
  800.     }
  801.     }
  802. #endif SOSP91
  803.     if (!(flags & FS_DEV_DONT_LOCK)) { 
  804.     Fsutil_HandleUnlock(devHandlePtr);
  805.     }
  806.     return(status);
  807. }
  808.  
  809. /*
  810.  *----------------------------------------------------------------------
  811.  *
  812.  * Fsio_DeviceWrite --
  813.  *
  814.  *      Write on a stream connected to a local peripheral device.
  815.  *    This is called from Fs_Write and Fsrmt_RpcWrite.
  816.  *
  817.  * Results:
  818.  *    SUCCESS unless there was an address error or I/O error.
  819.  *
  820.  * Side effects:
  821.  *    Write to the device.
  822.  *
  823.  *----------------------------------------------------------------------
  824.  */
  825. ReturnStatus
  826. Fsio_DeviceWrite(streamPtr, writePtr, remoteWaitPtr, replyPtr)
  827.     Fs_Stream        *streamPtr;    /* Open stream to the device. */
  828.     Fs_IOParam        *writePtr;    /* Read parameter block */
  829.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  830.     Fs_IOReply        *replyPtr;    /* Signal to return, if any */
  831. {
  832.     register Fsio_DeviceIOHandle    *devHandlePtr =
  833.         (Fsio_DeviceIOHandle *)streamPtr->ioHandlePtr;
  834.     ReturnStatus    status = SUCCESS;
  835.     register Fs_Device    *devicePtr = &devHandlePtr->device;
  836.     Address        userBuffer;
  837.     int            flags;
  838.     Boolean        copy;
  839.  
  840.     userBuffer = (Address) NIL;
  841.     flags = devHandlePtr->flags;
  842.     /*
  843.      * Don't lock if the device driver informed us upon open that 
  844.      * it doesn't want it.
  845.      */
  846.     if (!(flags & FS_DEV_DONT_LOCK)) { 
  847.     Fsutil_HandleLock(devHandlePtr);
  848.     }
  849.     /*
  850.      * Because the write could take a while and we aren't mapping in
  851.      * buffers, we have to allocate an extra buffer here so the
  852.      * buffer address is valid when the device's interrupt handler
  853.      * does its DMA. Don't do this malloc and copy if the device
  854.      * driver said it would handle it.
  855.      */
  856.     copy = ((writePtr->flags & FS_USER) && !(flags & FS_DEV_DONT_COPY));
  857.     if (copy) {
  858.     userBuffer = writePtr->buffer;
  859.         writePtr->buffer = (Address)malloc(writePtr->length);
  860.     if (Vm_CopyIn(writePtr->length, userBuffer, writePtr->buffer) != SUCCESS) {
  861.         status = SYS_ARG_NOACCESS;
  862.     }
  863.     }
  864.     if (status == SUCCESS) {
  865.     /*
  866.      * Put the process onto the write-wait list before attempting the write.
  867.      * This is to prevent races with the device's notification which
  868.      * happens from an interrupt handler.
  869.      */
  870.     Fsutil_WaitListInsert(&devHandlePtr->writeWaitList, remoteWaitPtr);
  871.     status = (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].write)(devicePtr,
  872.         writePtr, replyPtr);
  873.     if (status != FS_WOULD_BLOCK) {
  874.         Fsutil_WaitListRemove(&devHandlePtr->writeWaitList, remoteWaitPtr);
  875.     }
  876.     devHandlePtr->modifyTime = Fsutil_TimeInSeconds();
  877.     fs_Stats.gen.deviceBytesWritten += replyPtr->length;
  878. #ifdef SOSP91
  879.     if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  880.         if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  881.             (proc_RunningProcesses[0]->genFlags &
  882.             (PROC_FOREIGN | PROC_MIGRATING))) {
  883.         fs_SospMigStats.gen.deviceBytesWritten += replyPtr->length; 
  884.         }
  885.     }
  886. #endif SOSP91
  887.     }
  888.  
  889.     if (copy) {
  890.     free(writePtr->buffer);
  891.     writePtr->buffer = userBuffer;
  892.     }
  893.     if (!(flags & FS_DEV_DONT_LOCK)) { 
  894.     Fsutil_HandleUnlock(devHandlePtr);
  895.     }
  896.     return(status);
  897. }
  898.  
  899. /*
  900.  *----------------------------------------------------------------------
  901.  *
  902.  * Fsio_DeviceSelect --
  903.  *
  904.  *      Select on a stream connected to a local peripheral device.  This
  905.  *    ensures that the calling process is on a waiting list, then calls
  906.  *    the device driver's select routine.  If the select succeeds, then
  907.  *    the wait list items are removed.  The ordering of this is done to
  908.  *    prevent races between the select routine and the notification that
  909.  *    occurs at interrupt time.
  910.  *
  911.  * Results:
  912.  *    A return from the driver, should be SUCCESS unless the
  913.  *    device is offline or something.
  914.  *
  915.  * Side effects:
  916.  *    None.
  917.  *
  918.  *----------------------------------------------------------------------
  919.  */
  920. ReturnStatus
  921. Fsio_DeviceSelect(hdrPtr, waitPtr, readPtr, writePtr, exceptPtr)
  922.     Fs_HandleHeader    *hdrPtr;    /* Handle on device to select */
  923.     Sync_RemoteWaiter    *waitPtr;    /* Process info for remote waiting */
  924.     int         *readPtr;    /* Bit to clear if non-readable */
  925.     int         *writePtr;    /* Bit to clear if non-writeable */
  926.     int         *exceptPtr;    /* Bit to clear if non-exceptable */
  927. {
  928.     register Fsio_DeviceIOHandle *devHandlePtr = (Fsio_DeviceIOHandle *)hdrPtr;
  929.     register Fs_Device    *devicePtr = &devHandlePtr->device;
  930.     register ReturnStatus status;
  931.  
  932.     Fsutil_HandleLock(devHandlePtr);
  933.     if (waitPtr != (Sync_RemoteWaiter *)NIL) {
  934.     if (*readPtr) {
  935.         Fsutil_WaitListInsert(&devHandlePtr->readWaitList, waitPtr);
  936.     }
  937.     if (*writePtr) {
  938.         Fsutil_WaitListInsert(&devHandlePtr->writeWaitList, waitPtr);
  939.     }
  940.     if (*exceptPtr) {
  941.         Fsutil_WaitListInsert(&devHandlePtr->exceptWaitList, waitPtr);
  942.     }
  943.     }
  944.     status = (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].select)(devicePtr,
  945.             readPtr, writePtr, exceptPtr);
  946.  
  947.     if (waitPtr != (Sync_RemoteWaiter *)NIL) {
  948.     if (*readPtr != 0) {
  949.         Fsutil_WaitListRemove(&devHandlePtr->readWaitList, waitPtr);
  950.     }
  951.     if (*writePtr != 0) {
  952.         Fsutil_WaitListRemove(&devHandlePtr->writeWaitList, waitPtr);
  953.     }
  954.     if (*exceptPtr != 0) {
  955.         Fsutil_WaitListRemove(&devHandlePtr->exceptWaitList, waitPtr);
  956.     }
  957.     }
  958.     Fsutil_HandleUnlock(devHandlePtr);
  959.     return(status);
  960. }
  961.  
  962. /*
  963.  *----------------------------------------------------------------------
  964.  *
  965.  * Fsio_DeviceIOControl --
  966.  *
  967.  *      Write on a stream connected to a peripheral device.  Called from
  968.  *    FsDomainWrite.
  969.  *
  970.  * Results:
  971.  *    SUCCESS unless there was an address error or I/O error.
  972.  *
  973.  * Side effects:
  974.  *    Write to the device.
  975.  *
  976.  *----------------------------------------------------------------------
  977.  */
  978. ReturnStatus
  979. Fsio_DeviceIOControl(streamPtr, ioctlPtr, replyPtr)
  980.     Fs_Stream *streamPtr;        /* Stream to a device. */
  981.     Fs_IOCParam *ioctlPtr;        /* I/O Control parameter block */
  982.     Fs_IOReply *replyPtr;        /* Return length and signal */
  983. {
  984.     register Fsio_DeviceIOHandle *devHandlePtr =
  985.         (Fsio_DeviceIOHandle *)streamPtr->ioHandlePtr;
  986.     register Fs_Device    *devicePtr = &devHandlePtr->device;
  987.     register ReturnStatus status = SUCCESS;
  988.  
  989.     switch (ioctlPtr->command) {
  990.     case IOC_LOCK:
  991.     case IOC_UNLOCK:
  992.         Fsutil_HandleLock(devHandlePtr);
  993.         status = Fsio_IocLock(&devHandlePtr->lock, ioctlPtr,
  994.             &streamPtr->hdr.fileID);
  995.         Fsutil_HandleUnlock(devHandlePtr);
  996.         break;
  997.     case IOC_PREFIX:
  998.         break;
  999.     default:
  1000.         if (!(devHandlePtr->flags & FS_DEV_DONT_LOCK)) { 
  1001.         Fsutil_HandleLock(devHandlePtr);
  1002.         }
  1003.         status = (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].ioctl)
  1004.             (devicePtr, ioctlPtr, replyPtr);
  1005.         if (!(devHandlePtr->flags & FS_DEV_DONT_LOCK)) { 
  1006.         Fsutil_HandleUnlock(devHandlePtr);
  1007.         }
  1008.         break;
  1009.     }
  1010.     return(status);
  1011. }
  1012.  
  1013. /*
  1014.  *----------------------------------------------------------------------
  1015.  *
  1016.  * Fsio_DeviceGetIOAttr --
  1017.  *
  1018.  *      Get the I/O attributes for a device.  A copy of the access and
  1019.  *    modify times are kept at the I/O server.  This routine is called
  1020.  *    either from Fs_GetAttrStream or Fsrmt_RpcGetIOAttr to update
  1021.  *    the initial copy of the attributes obtained from the name server.
  1022.  *
  1023.  * Results:
  1024.  *    SUCCESS.
  1025.  *
  1026.  * Side effects:
  1027.  *    None.
  1028.  *
  1029.  *----------------------------------------------------------------------
  1030.  */
  1031. /*ARGSUSED*/
  1032. ReturnStatus
  1033. Fsio_DeviceGetIOAttr(fileIDPtr, clientID, attrPtr)
  1034.     Fs_FileID            *fileIDPtr;    /* FileID of device */
  1035.     int             clientID;    /* IGNORED */
  1036.     register Fs_Attributes    *attrPtr;    /* Attributes to update */
  1037. {
  1038.     register Fsio_DeviceIOHandle *devHandlePtr;
  1039.  
  1040.     devHandlePtr = Fsutil_HandleFetchType(Fsio_DeviceIOHandle, fileIDPtr);
  1041.     if (devHandlePtr != (Fsio_DeviceIOHandle *)NIL) {
  1042.     if (devHandlePtr->accessTime > attrPtr->accessTime.seconds) {
  1043.         attrPtr->accessTime.seconds = devHandlePtr->accessTime;
  1044.     }
  1045.     if (devHandlePtr->modifyTime > attrPtr->dataModifyTime.seconds) {
  1046.         attrPtr->dataModifyTime.seconds = devHandlePtr->modifyTime;
  1047.     }
  1048.     Fsutil_HandleRelease(devHandlePtr, TRUE);
  1049.     }
  1050.     return(SUCCESS);
  1051. }
  1052.  
  1053. /*
  1054.  *----------------------------------------------------------------------
  1055.  *
  1056.  * Fsio_DeviceSetIOAttr --
  1057.  *
  1058.  *      Set the I/O attributes for a device.  A copy of the access and
  1059.  *    modify times are kept at the I/O server.  This routine is called
  1060.  *    either from Fs_SetAttrStream or Fsrmt_RpcSetIOAttr to update
  1061.  *    the cached copy of the attributes.
  1062.  *
  1063.  * Results:
  1064.  *    SUCCESS.
  1065.  *
  1066.  * Side effects:
  1067.  *    None.
  1068.  *
  1069.  *----------------------------------------------------------------------
  1070.  */
  1071. /*ARGSUSED*/
  1072. ReturnStatus
  1073. Fsio_DeviceSetIOAttr(fileIDPtr, attrPtr, flags)
  1074.     Fs_FileID            *fileIDPtr;    /* FileID of device */
  1075.     register Fs_Attributes    *attrPtr;    /* Attributes to copy */
  1076.     int                flags;        /* What attrs to set */
  1077. {
  1078.     register Fsio_DeviceIOHandle *devHandlePtr;
  1079.  
  1080.     if (flags & FS_SET_TIMES) {
  1081.     devHandlePtr = Fsutil_HandleFetchType(Fsio_DeviceIOHandle, fileIDPtr);
  1082.     if (devHandlePtr != (Fsio_DeviceIOHandle *)NIL) {
  1083.         devHandlePtr->accessTime = attrPtr->accessTime.seconds;
  1084.         devHandlePtr->modifyTime = attrPtr->dataModifyTime.seconds;
  1085.         Fsutil_HandleRelease(devHandlePtr, TRUE);
  1086.     }
  1087.     }
  1088.     return(SUCCESS);
  1089. }
  1090.  
  1091.  
  1092. /*
  1093.  *----------------------------------------------------------------------
  1094.  *
  1095.  * Fsio_DevNotifyReader --
  1096.  *
  1097.  *    Fsio_DevNotifyReader is available to device driver interrupt handlers
  1098.  *    that need to notify waiting processes that the device is readable.
  1099.  *    It schedules a process level call to ReadNotify, which
  1100.  *    in turn iterates down the list of handles for the device waking up
  1101.  *    all read waiters.
  1102.  *
  1103.  * Results:
  1104.  *    None
  1105.  *
  1106.  * Side effects:
  1107.  *    Schedules a call to DevListNotify, which in turn calls
  1108.  *    Fsutil_WaitListNotify to schedule any waiting readers.
  1109.  *
  1110.  *----------------------------------------------------------------------
  1111.  */
  1112. void
  1113. Fsio_DevNotifyReader(notifyToken)
  1114.     Fs_NotifyToken notifyToken;
  1115. {
  1116.     register Fsio_DeviceIOHandle *devHandlePtr = (Fsio_DeviceIOHandle *)notifyToken;
  1117.  
  1118.     if ((devHandlePtr == (Fsio_DeviceIOHandle *)NIL) ||
  1119.     (devHandlePtr->notifyFlags & FS_READABLE)) {
  1120.     return;
  1121.     }
  1122.     if (devHandlePtr->hdr.fileID.type != FSIO_LCL_DEVICE_STREAM) {
  1123.     printf("Fsio_DevNotifyReader, bad handle\n");
  1124.     }
  1125.     devHandlePtr->notifyFlags |= FS_READABLE;
  1126.     Proc_CallFunc(ReadNotify, (ClientData) devHandlePtr, 0);
  1127. }
  1128.  
  1129. static void
  1130. ReadNotify(data, callInfoPtr)
  1131.     ClientData        data;
  1132.     Proc_CallInfo    *callInfoPtr;
  1133. {
  1134.     register Fsio_DeviceIOHandle *devHandlePtr = (Fsio_DeviceIOHandle *)data;
  1135.     if (devHandlePtr->hdr.fileID.type != FSIO_LCL_DEVICE_STREAM) {
  1136.     printf("ReadNotify, lost device handle\n");
  1137.     } else {
  1138.     devHandlePtr->notifyFlags &= ~FS_READABLE;
  1139.     Fsutil_WaitListNotify(&devHandlePtr->readWaitList);
  1140.     }
  1141.     callInfoPtr->interval = 0;
  1142. }
  1143.  
  1144.  
  1145. /*
  1146.  *----------------------------------------------------------------------
  1147.  *
  1148.  * Fsio_DevNotifyWriter --
  1149.  *
  1150.  *    Fsio_DevNotifyWriter is available to device driver interrupt handlers
  1151.  *    that need to notify waiting processes that the device is writeable.
  1152.  *    It schedules a process level call to Fs_WaitListNotifyStub on the
  1153.  *    devices's write wait list.
  1154.  *
  1155.  * Results:
  1156.  *    None
  1157.  *
  1158.  * Side effects:
  1159.  *    Schedules a call to Fs_WaitListNotifyStub.
  1160.  *
  1161.  *----------------------------------------------------------------------
  1162.  */
  1163. void
  1164. Fsio_DevNotifyWriter(notifyToken)
  1165.     Fs_NotifyToken notifyToken;
  1166. {
  1167.     register Fsio_DeviceIOHandle *devHandlePtr = (Fsio_DeviceIOHandle *)notifyToken;
  1168.  
  1169.     if ((devHandlePtr == (Fsio_DeviceIOHandle *)NIL) ||
  1170.     (devHandlePtr->notifyFlags & FS_WRITABLE)) {
  1171.     return;
  1172.     }
  1173.     if (devHandlePtr->hdr.fileID.type != FSIO_LCL_DEVICE_STREAM) {
  1174.     printf("Fsio_DevNotifyWriter, bad handle\n");
  1175.     return;
  1176.     }
  1177.     devHandlePtr->notifyFlags |= FS_WRITABLE;
  1178.     Proc_CallFunc(WriteNotify, (ClientData) devHandlePtr, 0);
  1179. }
  1180.  
  1181. static void
  1182. WriteNotify(data, callInfoPtr)
  1183.     ClientData        data;
  1184.     Proc_CallInfo    *callInfoPtr;
  1185. {
  1186.     register Fsio_DeviceIOHandle *devHandlePtr = (Fsio_DeviceIOHandle *)data;
  1187.     if (devHandlePtr->hdr.fileID.type != FSIO_LCL_DEVICE_STREAM) {
  1188.     printf( "WriteNotify, lost device handle\n");
  1189.     } else {
  1190.     devHandlePtr->notifyFlags &= ~FS_WRITABLE;
  1191.     Fsutil_WaitListNotify(&devHandlePtr->writeWaitList);
  1192.     }
  1193.     callInfoPtr->interval = 0;
  1194. }
  1195.  
  1196.  
  1197.  
  1198. /*
  1199.  *----------------------------------------------------------------------
  1200.  *
  1201.  * Fsio_DevNotifyException --
  1202.  *
  1203.  *    This is available to device driver interrupt handlers
  1204.  *    that need to notify waiting processes that there is an exception
  1205.  *    on the device.  This is only useful for processes waiting on
  1206.  *    exceptions in select.  This is not currently used.
  1207.  *    It schedules a process level call to Fs_WaitListNotifyStub on the
  1208.  *    devices's exception wait list.
  1209.  *
  1210.  * Results:
  1211.  *    None
  1212.  *
  1213.  * Side effects:
  1214.  *    Schedules a call to Fs_WaitListNotifyStub.
  1215.  *
  1216.  *----------------------------------------------------------------------
  1217.  */
  1218. void
  1219. Fsio_DevNotifyException(notifyToken)
  1220.     Fs_NotifyToken notifyToken;
  1221. {
  1222.     register Fsio_DeviceIOHandle *devHandlePtr = (Fsio_DeviceIOHandle *)notifyToken;
  1223.  
  1224.     if (devHandlePtr == (Fsio_DeviceIOHandle *)NIL) {
  1225.     return;
  1226.     }
  1227.     Proc_CallFunc(ExceptionNotify, (ClientData) devHandlePtr, 0);
  1228. }
  1229.  
  1230. static void
  1231. ExceptionNotify(data, callInfoPtr)
  1232.     ClientData        data;
  1233.     Proc_CallInfo    *callInfoPtr;
  1234. {
  1235.     register Fsio_DeviceIOHandle *devHandlePtr = (Fsio_DeviceIOHandle *)data;
  1236.     Fsutil_WaitListNotify(&devHandlePtr->exceptWaitList);
  1237.     callInfoPtr->interval = 0;
  1238. }
  1239.  
  1240.  
  1241. /*
  1242.  *----------------------------------------------------------------------
  1243.  *
  1244.  * Fsio_DeviceRecovTestUseCount --
  1245.  *
  1246.  *    For recovery testing, return the use count of the io handle.    
  1247.  *
  1248.  * Results:
  1249.  *    The use count.
  1250.  *
  1251.  * Side effects:
  1252.  *    None.
  1253.  *
  1254.  *----------------------------------------------------------------------
  1255.  */
  1256. int
  1257. Fsio_DeviceRecovTestUseCount(handlePtr)
  1258.     Fsio_DeviceIOHandle *handlePtr;
  1259. {
  1260.     return handlePtr->use.ref;
  1261. }
  1262.  
  1263. /*
  1264.  *----------------------------------------------------------------------
  1265.  *
  1266.  * Fsio_BootTimeTtyOpen --
  1267.  *
  1268.  *    This is a stripped down version of Fsio_DeviceIoOpen
  1269.  *    that is used to invoke the tty driver open routine
  1270.  *    at boot time.  The important thing to get right is
  1271.  *    that the tty driver has to be passed the real FS
  1272.  *    I/O handle for the device so notifications work.
  1273.  *
  1274.  * Results:
  1275.  *    SUCCESS or a device dependent open error code.
  1276.  *
  1277.  * Side effects:
  1278.  *    Sets up and installs the console's ioHandle.  The tty open
  1279.  *    routine is called so L1/break/F1 key processing for
  1280.  *    Dev_InvokeConsole command is enabled.
  1281.  *    The associated FS handle is unlocked
  1282.  *    upon exit, but its reference count has been incremented.
  1283.  *
  1284.  *----------------------------------------------------------------------
  1285.  */
  1286. ReturnStatus
  1287. Fsio_BootTimeTtyOpen()
  1288. {
  1289.     ReturnStatus     status;
  1290.     Fs_FileID        ttyFileID;
  1291.     Fsio_DeviceIOHandle    *devHandlePtr;
  1292.  
  1293.     /*
  1294.      * Set up the console's fileID.  This sets the console
  1295.      * unit number to 0, although this is cleverly mapped by the
  1296.      * ttyDriver to a serial line if the EEPROM is properly configured.
  1297.      */
  1298.     ttyFileID.type = FSIO_LCL_DEVICE_STREAM;
  1299.     ttyFileID.serverID = rpc_SpriteID;
  1300.     ttyFileID.major = DEV_TERM;
  1301.     ttyFileID.minor = 0;
  1302.     (void)FsioDeviceHandleInit(&ttyFileID, "/dev/console", &devHandlePtr);
  1303.     /*
  1304.      * The device driver open routine gets the device specification,
  1305.      * the useFlags, and a token passed to Fs_NotifyReader
  1306.      * or Fs_NotifyWriter when the device becomes ready for I/O.
  1307.      */
  1308.     if (DEV_TYPE_INDEX(devHandlePtr->device.type) >= devNumDevices) {
  1309.     status = FS_DEVICE_OP_INVALID;
  1310.     } else {
  1311.     int flags = 0;
  1312. /* XXX */ printf("Fsio_BootTimeTtyOpen: spriteID %d devHandle <%x>\n",
  1313.             rpc_SpriteID, devHandlePtr);
  1314.     status = (*devFsOpTable[DEV_TYPE_INDEX(devHandlePtr->device.type)].open)
  1315.             (&devHandlePtr->device, FS_READ|FS_WRITE, 
  1316.               (Fs_NotifyToken)devHandlePtr, &flags);
  1317.     }
  1318.     /*
  1319.      * Unlock the handle.  This leaves an extra reference just
  1320.      * to make sure the file system handle doesn't get scavenged.
  1321.      */
  1322.     Fsutil_HandleUnlock(devHandlePtr);
  1323.     return(status);
  1324. }
  1325.  
  1326.  
  1327. /*
  1328.  *----------------------------------------------------------------------
  1329.  *
  1330.  * Fsio_DeviceMmap --
  1331.  *
  1332.  *    Do a device-specific mmap operation.
  1333.  *
  1334.  * Results:
  1335.  *    SUCCESS or FAILURE.
  1336.  *
  1337.  * Side effects:
  1338.  *    Kernel memory mapped into user space.
  1339.  *
  1340.  *----------------------------------------------------------------------
  1341.  */
  1342. ReturnStatus
  1343. Fsio_DeviceMmap(streamPtr, startAddr, length, offset, newAddrPtr)
  1344.     Fs_Stream        *streamPtr;    /* Stream to device. */
  1345.     Address        startAddr;    /* Requested starting virt. addr. */
  1346.     int            length;        /* Length of mapped segment. */
  1347.     int            offset;        /* Offset into mapped file. */
  1348.     Address        *newAddrPtr;
  1349. {
  1350.     Fs_Device        *devicePtr;
  1351.     Fsio_DeviceIOHandle    *ioHandlePtr;
  1352.     ReturnStatus    status;
  1353.  
  1354.     if (streamPtr->ioHandlePtr->fileID.type != FSIO_LCL_DEVICE_STREAM) {
  1355.     printf("Fsio_DeviceMmap passed something that wasn't a device.\n");
  1356.     return FAILURE;
  1357.     }
  1358.     ioHandlePtr = (Fsio_DeviceIOHandle *) streamPtr->ioHandlePtr;
  1359.     devicePtr = &(ioHandlePtr->device);
  1360.     if (DEV_TYPE_INDEX(devicePtr->type) >= devNumDevices) {
  1361.     return  FS_DEVICE_OP_INVALID;
  1362.     }
  1363.  
  1364.     status = (*devFsOpTable[DEV_TYPE_INDEX(devicePtr->type)].mmap)
  1365.         (devicePtr, startAddr, length, offset, newAddrPtr);
  1366.  
  1367.     return status;
  1368. }
  1369.  
  1370.